package org.yxj.customlibrary.v;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;

import org.yxj.customlibrary.util.LogUtil;
import org.yxj.customlibrary.util.ZoomViewUtil;


/**
 * 编辑定制文字缩放
 *
 * @author yxj on 2022/7/27
 */
public class EditCustomTextView extends FrameLayout {


    public static final String TAG = "[EditCustomTextView]->";


    /**
     * 模式
     */
    public enum Mode {
        /**
         * 缩放
         */
        ZOOM,
        /**
         * 拖拽
         */
        Drag,
        /**
         * 旋转
         */
        Rotation,
        /**
         * 默认状态
         */
        None
    }


    /**
     * 默认模式
     */
    private Mode mode;


    /**
     * 最大放大倍数
     */
    private int mMaxScale = 4;
    /**
     * 做小缩放倍数
     */
    private int mMinScale = 1;
    /**
     * 记录view历史缩放
     */
    private Matrix matrix = new Matrix();
    /**
     * 按下两指间的长度
     */
    private float startDis = 0;

    /**
     * 实时缩放的时两指间的距离
     */
    private float endDis = 0;

    /**
     * 当前缩放比例
     */
    private float scale;


    /**
     * 第一个触点按钮的坐标
     */
    private PointF downPoint = new PointF();
    /**
     * 记录平移
     */
    private PointF tranPoint = new PointF();



    public EditCustomTextView(Context context) {
        this(context, null);
    }


    public EditCustomTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }


    public EditCustomTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        try {
            return super.onInterceptTouchEvent(ev);
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        }
        return false;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        /*当前触摸点数据*/
        int pointerCount = event.getPointerCount();

        float x = event.getX();
        float y = event.getY();

        switch (event.getActionMasked()) {

            /**
             * 单指触碰
             */
            case MotionEvent.ACTION_DOWN:
                mode = Mode.Drag;
                downPoint.x = x;
                downPoint.y = y;
                LogUtil.LOG_V("[TouchEvent]->ACTION_DOWN");
                break;


            /**
             * 多指触碰模式
             * 1、缩放
             * 2、旋转
             */
            case MotionEvent.ACTION_POINTER_DOWN:
                LogUtil.LOG_V("[TouchEvent]->ACTION_POINTER_DOWN");
                mode = Mode.ZOOM;
                startDis = ZoomViewUtil.distanceBetweenLength(event);
                break;


            /**
             * 触摸点移动
             */
            case MotionEvent.ACTION_MOVE:
                LogUtil.LOG_V("[TouchEvent]->ACTION_MOVE");
                if (pointerCount > 1) {
                    mode = Mode.ZOOM;
                    Zoom(event);
                } else if (mode == Mode.Drag) {
                    drag(event);
                } else {
                    mode = Mode.None;
                }
                break;


            /**
             * 结束多指模式
             */
            case MotionEvent.ACTION_POINTER_UP:
                LogUtil.LOG_V("[TouchEvent]->ACTION_POINTER_UP");
                mode = Mode.None;
                break;


            /**
             * 所有触摸点都已离开
             */
            case MotionEvent.ACTION_UP:
                LogUtil.LOG_V("[TouchEvent]->ACTION_UP");
                mode = Mode.None;
                break;
        }
        return true;
    }


    /**
     * 缩放模式实现
     *
     * @param event
     */
    private void Zoom(MotionEvent event) {
        endDis = ZoomViewUtil.distanceBetweenLength(event);

        /**当前动作产生的缩放值*/
        scale = (float) (endDis * 1.0 / startDis);
        /**控制缩放范围最小最大缩放值 1 - 4 */
        float tempScale = checkScale(scale);
        setScaleX(tempScale);
        setScaleY(tempScale);
        /**记录当前缩放值*/
        matrix.setScale(tempScale, tempScale);


        /**缩放的同时也需要控制边界 不能越界*/
        drag(event);
    }


    /**
     * 获取当前view的大小
     */
    public float[] getCurrentViewSize() {
        float scale = getLastScale();
        return new float[]{getMeasuredWidth() * scale, getMeasuredHeight() * scale};
    }


    /**
     * 检测缩放比例范围
     *
     * @param scale
     * @return
     */
    private float checkScale(float scale) {
        float radio = getLastScale();
        float tempScale = scale * radio;

        if (tempScale * 1.0 / mMaxScale >= 1) {
            /*超出了最大缩放*/
            tempScale = mMaxScale;
        } else if (tempScale * 1.0 / mMinScale <= mMinScale) {
            /*小于了最最小缩放*/
            tempScale = mMinScale;
        }
        return tempScale;
    }


    /**
     * 当前缩放值
     *
     * @return
     */
    private float getLastScale() {
        float[] values = new float[9];
        matrix.getValues(values);
        return values[Matrix.MSCALE_X];
    }


    /**
     * 拖拽模式实现
     *
     * @param event
     */
    private void drag(MotionEvent event) {
        /**
         * 平移值
         */
        float[] values = checkTranBorder(event);


        /**开始执行移动*/
        setTranslationX(values[0]);
        setTranslationY(values[1]);

        /**
         * 记录上一次移动
         */
        tranPoint.x = values[0];
        tranPoint.y = values[1];


        LogUtil.LOG_V("[tranPoint]->" + tranPoint.toString());
    }




    /**
     * 检测边界  防止移动到屏幕外面去了
     *
     * @param event
     */
    private float[] checkTranBorder(MotionEvent event) {
        /**当前拖拽需要移动  x  y  方向上的距离*/
        float tranX = event.getX() - downPoint.x + tranPoint.x;
        float tranY = event.getY() - downPoint.y + tranPoint.y;

        /**当前view的大小  缩放后的*/
        float[] size = getCurrentViewSize();


        /**可以平移最大距离*/
        float maxTranX = (float) ((size[0] - getMeasuredWidth() * 1.0) / 2);
        /**左边界*/
        if (tranX >= maxTranX) {
            tranX = maxTranX;
        } else if (maxTranX <= Math.abs(tranX)) {
            tranX = -maxTranX;
        }


        float maxTranY = (float) ((size[1] - getMeasuredHeight()) * 1.0 / 2);
        /**上边界*/
        LogUtil.LOG_V("[tranPoint]-> 0000  " + maxTranY);
        if (tranY >= maxTranY) {
            tranY = maxTranY;
        } else if (maxTranY <= Math.abs(tranY)) {
            /**下边界*/
            tranY = -maxTranY;
        }
        return new float[]{tranX, tranY};
    }
}
